package com.yuan.util.web;

import com.yuan.util.io.DataUtil;
import com.yuan.util.string.StrUtil;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;

/**
 * 网页请求工具类
 *
 * @author moqw
 * @version 1.0
 * @CreateDate 2018/4/20 16:44
 * @UpdateDate 2018/4/20 16:44
 */
public class HttpUtil {

    /**
     * 默认编码格式
     */
    private static String DEFAULT_ENCODE = "UTF-8";
    /**
     * 请求失败重试次数
     */
    private static int RETRY_COUNT = 3;

    public static String httpGet(String url) throws Exception {
        return httpGet(url, new HttpClient());
    }

    public static HttpResponse openUrl(String url) throws Exception {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet method = new HttpGet(url);
        return client.execute(method);
    }

    /**
     * HttpGet请求封装方法，可指定client执行请求，若client为null则创建一个新的client发起请求
     *
     * @param url    请求地址
     * @param client 请求client
     * @return 请求结果（转换成字符串）
     */
    public static String httpGet(String url, HttpClient client) throws Exception {
        GetMethod method = new GetMethod(url);
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler(RETRY_COUNT, false));//设置失败重试
        byte[] responseBody;
        String charSet;
        String rs;
        try {
            client.executeMethod(method);
            InputStream stream = method.getResponseBodyAsStream();
            responseBody = DataUtil.streamToByte(stream);
            charSet = method.getResponseCharSet();//响应的字符编码
            if (charSet == null) {
                charSet = DEFAULT_ENCODE;
            }
            rs = new String(responseBody, charSet);
            stream.close();
        } finally {
            method.releaseConnection();
        }
        return rs;
    }

    /**
     * HttpPost请求封装方法，可指定client执行请求，若client为null则创建一个新的client发起请求
     *
     * @param url    请求地址
     * @param params 请求参数
     * @param client 请求client
     * @return 请求结果（转换成字符串）
     */
    public static String httpPost(String url, Map params, HttpClient client, boolean encode, String charset) throws Exception {
        PostMethod method = new PostMethod(url);
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler(RETRY_COUNT, false));//设置失败重试
        String useCharset = charset == null ? DEFAULT_ENCODE : charset;
        if (params != null) {
            Set keys = params.keySet();//设置请求参数
            for (Object key : keys) {
                String val = StrUtil.trim(params.get(key));
                if (encode) {
                    val = URLEncoder.encode(val, useCharset);
                }
                method.setParameter(StrUtil.toStr(key), val);
            }
        }
        byte[] responseBody;
        String charSet;
        String rs = null;
        try {
            client.executeMethod(method);
            InputStream stream = method.getResponseBodyAsStream();
            responseBody = DataUtil.streamToByte(stream);
//            responseBody = method.getResponseBody();
            charSet = method.getResponseCharSet();//响应的字符编码
            if (charSet == null) {
                charSet = DEFAULT_ENCODE;
            }
            rs = new String(responseBody, charSet);
            stream.close();
        } finally {
            method.releaseConnection();
        }
        return rs;
    }

    public static String httpPost(String url, Map params) throws Exception {
        return httpPost(url, params, new HttpClient(), false, null);
    }

    public static String httpPost(String url, Map params, boolean encode, String charset) throws Exception {
        return httpPost(url, params, new HttpClient(), encode, charset);
    }

    /**
     * Post提交文件表单
     *
     * @param url
     * @param reqParam
     * @return
     * @throws Exception
     */
    public static String postFileMultiPart(String url, Map<String, ContentBody> reqParam) throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httppost = new HttpPost(url);
            RequestConfig defaultRequestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(5000).build();
            httppost.setConfig(defaultRequestConfig);
            MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
            for (Map.Entry<String, ContentBody> param : reqParam.entrySet()) {
                multipartEntityBuilder.addPart(param.getKey(), param.getValue());
            }
            HttpEntity reqEntity = multipartEntityBuilder.build();
            httppost.setEntity(reqEntity);
            CloseableHttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                return EntityUtils.toString(entity, DEFAULT_ENCODE);
            }
        } finally {
            httpclient.close();
        }
        return null;
    }

    public static String getDefaultEncode() {
        return DEFAULT_ENCODE;
    }

    public static void setDefaultEncode(String defaultEncode) {
        DEFAULT_ENCODE = defaultEncode;
    }

    public static int getRetryCount() {
        return RETRY_COUNT;
    }

    public static void setRetryCount(int retryCount) {
        RETRY_COUNT = retryCount;
    }

}
